package au.com.mason.propertyTracker.util;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;

import au.com.mason.propertyTracker.domain.SaleProperty;

public class RealEstateResponseParser {

	private String response;
	private int startIndex = 0;

	public RealEstateResponseParser(String response) {
		this.response = StringUtils.trimToEmpty(response);
		if (response.indexOf("People Also Viewed") != -1) {
			this.response = this.response.substring(0, this.response.indexOf("People Also Viewed"));
		}
	}
	
	public String getImgaeURL() {
		if (response.indexOf("<div id='mainPhoto'") != -1) {
			int startIndex = response.indexOf("<img src=\"", response.indexOf("<div id='mainPhoto'")) + 10;
			int endIndex = response.indexOf(".jpg", startIndex);

			return response.substring(startIndex, endIndex);
		}
		
		return "";
	}
	
	public BigDecimal getPropertyId() {
		int startIndex = response.indexOf("<span class=\"property_id\">") + 26;
		int endIndex = response.indexOf("<", startIndex);
		
		String result = response.substring(startIndex, endIndex);
		result = result.replace("Property No. ", "");
		
		return getValueIfNumeric(result, "monitor");
	}
	
	public String getAddress() {
		String address = getAddressString();
		
		if (address.indexOf("contact agent") != -1 || address.indexOf("address available on request") != -1) {
			return "No Address Supplied";
			
		}
		
		address = address.substring(0, address.lastIndexOf(","));
		address = address.substring(0, address.lastIndexOf(","));
		
		return address;
	}
	
	public String getSuburbName() {
		String suburbName = getAddressString();
		
		if (suburbName.indexOf("contact agent") != -1 || suburbName.indexOf("address available on request") != -1) {
			return suburbName.substring(0, suburbName.indexOf(","));
		}
		if (suburbName.trim().equals("Bendigo")) suburbName = "Bendigo Central";
		
		suburbName = suburbName.substring(0, suburbName.lastIndexOf(","));
		suburbName = suburbName.substring(suburbName.lastIndexOf(",") + 1).trim();
		
		return suburbName;
	}
	
	public String getPostcode() {
		String postCode = getAddressString();
		
		postCode = postCode.substring(postCode.lastIndexOf(","));
		postCode = postCode.substring(postCode.length() - 4);
		
		return postCode;
	}
	
	public BigDecimal[] getPrices(String address) {
		int startIndex = response.indexOf("<li class=\"price\">") + 56;
		int endIndex = response.indexOf("<", startIndex);
		String priceString = response.substring(startIndex, endIndex);
		priceString = parseString(priceString);
		BigDecimal priceFrom = null;
		BigDecimal priceTo = null;
		if (priceString.indexOf("TenantEnquiryRange") != -1 || priceString.indexOf("TenantInquiryRange") != -1) {
			priceString = priceString.replace("TenantEnquiryRange", "");
			priceString = priceString.replace("TenantInquiryRange", "");
			String[] vals = priceString.split("-");
			BigDecimal startRange = getValueIfNumeric(vals[0], address);
			priceFrom = startRange;
			if (vals.length > 1) {
				BigDecimal endRange = getValueIfNumeric(vals[1], address);
				priceFrom = new BigDecimal(startRange.intValue() + (endRange.intValue() - startRange.intValue())/2);
			}
		}
		else if (priceString.indexOf("-") != -1) {
			String[] prices = priceString.split("-");
			priceFrom = getValueIfNumeric(prices[0], address);
			priceTo = getValueIfNumeric(prices[1], address);
		}
		else {
			priceFrom = getValueIfNumeric(priceString, address);
		}
		
		return new BigDecimal[] {priceFrom, priceTo};
	}
	
	public BigDecimal getNumberOfBedrooms(String url) {
		BigDecimal numberBedrooms = null;
		if (response.indexOf("<li class='first'><span>") != -1) {
			int startIndex = response.indexOf("<li class='first'><span>") + 24;
			int endIndex = response.indexOf("<", startIndex);
			
			numberBedrooms = getValueIfNumeric(response.substring(startIndex, endIndex), url);
		}
		
		return numberBedrooms;
	}
	
	public BigDecimal getNumberOfBathrooms(String url) {
		BigDecimal numberBathrooms = null;
		if (response.indexOf("alt=\"Bedrooms\" /></li> <li><span>") != -1) {
			int startIndex = response.indexOf("alt=\"Bedrooms\" /></li> <li><span>") + 33;
			int endIndex = response.indexOf("<", startIndex);
			
			numberBathrooms = getValueIfNumeric(response.substring(startIndex, endIndex), url);
		}
		
		return numberBathrooms;
	}
	
	public BigDecimal getNumberOfCarSpaces(String url) {
		BigDecimal numberCarSpaces = null;
		if (response.indexOf("alt=\"Bathrooms\" /></li> <li><span>") != -1) {
			int startIndex = response.indexOf("alt=\"Bathrooms\" /></li> <li><span>") + 34;
			int endIndex = response.indexOf("<", startIndex);
			numberCarSpaces = getValueIfNumeric(response.substring(startIndex, endIndex), url);
		}
		
		return numberCarSpaces;
	}
	
	public String getDescription() {
		int startIndex = response.indexOf("<p class=\"body\">") + 16;
		int endIndex = response.indexOf("</p>", startIndex);
		
		return response.substring(startIndex, endIndex);
	}
	
	public boolean isUnderContract() {
		return response.indexOf("Under Contract") != -1 || response.indexOf("Under Offer") != -1 || response.indexOf("UNDER CONTRACT") != -1 || response.indexOf("UNDER OFFER") != -1 || response.indexOf("the property has been sold, leased, or removed for some other reason") != -1;
	}
	
	public boolean isSold() {
		return response.indexOf("<li id='sold' class='active'>") != -1;
	}
	
	public String getNextNew() {
		int newIndex = response.indexOf("<span class=\"new\">", startIndex);
		String temp = response.substring(startIndex, newIndex);
		int aHrefIndex = temp.lastIndexOf("<a href=") + 9;
		String url = temp.substring(aHrefIndex, temp.indexOf("'", aHrefIndex));
		
		startIndex = newIndex + 18;
		
		return url;
	}
	
	public boolean hasNew() {
		return response.indexOf("<span class=\"new\">", startIndex) != -1;
	}
	
	public SaleProperty getSaleProperty(String url) {
		String address = getAddress();
		BigDecimal[] prices = getPrices(address);
		
		SaleProperty property = new SaleProperty();
		property.setImageUrl(getImgaeURL());
		property.setStreetAddress(address);
		property.setPriceFrom(prices[0]);
		property.setPriceTo(prices[1]);
		property.setRealEstatePropertyId(getPropertyId());
		property.setNumberBedrooms(getNumberOfBedrooms(url));
		property.setNumberBathrooms(getNumberOfBathrooms(url));
		property.setNumberCarSpaces(getNumberOfCarSpaces(url));
		property.setDescription(getDescription());
		property.setUrl(url);
		
		return property;
	}
	
	public List<String> getUrls() {
		List<String> urls = new ArrayList<String>();
		while (hasNew()) {
			urls.add("http://www.realestate.com.au" + getNextNew());
		}
		return urls;
	}
	
	private int getAddressStartIndex() {
		return response.indexOf("</span><h1>") + 11;
	}
	
	private String getAddressString() {
		return response.substring(getAddressStartIndex(), response.indexOf("</h1>", getAddressStartIndex() + 1));
	}
	
	private String parseString(String result) {
		
		result = result.replace(",", "");
		result = result.replace("$", "");
		result = result.replace("From", "");
		result = result.replace("weekly", "");
		result = result.replace("pw", "");
		result = result.replace("PW", "");
		result = result.replace("/", "");
		result = result.replace(" ", "");
		result = result.replace("EACH", "");
		result = result.replace("Each", "");
		result = result.replace("each", "");
		result = result.replace("Above", "");
		result = result.replace("Wk", "");
		result = result.replace("wk", "");
		result = result.replace("EPR", "");
		result = result.replace("OBO", "");
		result = result.replace(".00", "");
		result = result.replace("Quoting", "");
		result = result.replace("PrivateSale:", "");
		result = result.replace("PrivateSale", "");
		result = result.replace("perweek", "").trim();
		result = result.replace("PerWeek", "").trim();
		result = result.replace("K", "000");
		result = result.replace("k", "000");
		result = result.replace("PriceGuide:", "");
		result = result.replace("Guide:", "");
		result = result.replace("ByNeg", "");
		result = result.replace("+", "");
		result = result.replace("PlusBuyers", "");
		result = result.replace("Buyers", "");
		result = result.replace("Plus", "");
		result = result.replace("PLUS", "");
		result = result.replace("plus", "");
		result = result.replace("ForSale", "");
		result = result.replace("OffersAround", "");
		result = result.replace("OffersOver", "");
		result = result.replace("Offersover", "");
		result = result.replace("BuyerRanged:", "");
		result = result.replace("BuyerRanged", "");
		result = result.replace("Neg.Over", "");
		result = result.replace("Neg.Btw.", "");
		result = result.replace("Neg", "");
		result = result.replace("to", "-");
		
		if ((result.indexOf("M") != -1 || result.indexOf("mill") != -1) && result.indexOf(".") != -1) {
			result = result.replace(".", "");
			result = result.replace("M", "");
			result = result.replace("mill", "");
			if (result.length() == 2) {
				result += "00000";
			}
			else if (result.length() == 3) {
				result += "0000";
			}
		}
		
		return result;
	}
	
	private BigDecimal getValueIfNumeric(String value, String address) {
		BigDecimal numericValue = null;
		
		value = parseString(value);
		
		try {
			numericValue = new BigDecimal(value);
		}
		catch (NumberFormatException e) {
			System.out.println("NumberFormatException - could not convert " + value + " for address " + address);
			e.printStackTrace();
		}
		
		return numericValue;
	}
	
}
